package org.oslims.server.service.impl;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Set;

import net.sf.gilead.gwt.GwtConfigurationHelper;
import net.sf.gilead.gwt.PersistentRemoteService;

import org.hibernate.Session;
import org.oslims.client.service.RequestService;
import org.oslims.domain.Report;
import org.oslims.domain.Request;
import org.oslims.server.dao.ReportDao;
import org.oslims.server.dao.RequestDao;
import org.oslims.server.dao.hbm.HbmReportDao;
import org.oslims.server.dao.hbm.HbmRequestDao;
import org.oslims.server.dao.util.HibernateUtil;

import com.google.gwt.validation.client.InvalidConstraint;
import com.google.gwt.validation.client.interfaces.IValidator;
import com.google.gwt.validation.server.ServerValidator;

public class RequestServiceImpl extends PersistentRemoteService implements RequestService {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4464139023786525836L;

	RequestDao requestDao;
	ReportDao reportDao;

	IValidator<Request> requestValidator = new ServerValidator<Request>();

	public RequestServiceImpl() {
		requestDao = new HbmRequestDao();
		reportDao = new HbmReportDao();

		net.sf.gilead.core.hibernate.HibernateUtil hibernateUtil = new net.sf.gilead.core.hibernate.HibernateUtil(HibernateUtil.getSessionFactory());
		setBeanManager(GwtConfigurationHelper.initGwtStatelessBeanManager(hibernateUtil));
	}

	@Override
	public List<Request> getAllRequest() {
		Session session = HibernateUtil.getSession();
		requestDao.setSession(session);

		List<Request> result = requestDao.findAllWithSamples();

		session.close();

		return result;
	}

	@Override
	public void saveOrUpdateRequest(Request request) {

		Set<InvalidConstraint<Request>> violations = requestValidator.validate(request);

		if (violations.size() == 0) { // Only process the entity if valid!!!
			Session session = HibernateUtil.getSession();
			session.beginTransaction();
			try {
				requestDao.setSession(session);

				if (request.getId() == null) { // Generate the code for a new
					// request
					Request lastRequest = requestDao.findLastRequest();
					Calendar calendar = Calendar.getInstance();
					Integer year = calendar.get(Calendar.YEAR);
					year = Integer.parseInt(year.toString().substring(2, 4));

					NumberFormat prefix = new DecimalFormat("00");
					NumberFormat general = new DecimalFormat("00000");

					String newCode = "";
					if (lastRequest == null) {
						newCode = prefix.format(year) + "001";
					} else {
						Integer lastYear = Integer.parseInt(lastRequest.getCode().substring(0, 2));
						if (lastYear < year) {
							newCode = prefix.format(year) + "001";
						} else {
							Integer code = Integer.parseInt(lastRequest.getCode());
							code = code + 1;
							newCode = general.format(code);
						}
					}

					request.setCode(newCode);
				}

				requestDao.makePersistent(request);
				session.getTransaction().commit();
			} catch (RuntimeException e) {
				session.getTransaction().rollback();
				throw e;
			} finally {
				session.close();
			}
		}
	}

	@Override
	public void releaseRequests(List<Request> requests) {
		Session session = HibernateUtil.getSession();
		requestDao.setSession(session);
		session.beginTransaction();

		for (Request request : requests) {
			request.setState("Released");
			requestDao.makePersistent(request);
		}

		session.getTransaction().commit();
		session.close();
	}

	@Override
	public void closeRequests(List<Request> requests) {
		Session session = HibernateUtil.getSession();
		requestDao.setSession(session);
		session.beginTransaction();

		for (Request request : requests) {
			request.setState("Closed");
			requestDao.makePersistent(request);
		}

		session.getTransaction().commit();
		session.close();
	}

	@Override
	public Request findByCode(String requestCode) {
		Session session = HibernateUtil.getSession();
		requestDao.setSession(session);

		Request example = new Request();
		example.setCode(requestCode);

		System.out.println(requestCode);

		List<Request> result = requestDao.findByExample(example);

		session.close();

		if (result.size() > 0) {
			return result.get(0);
		}

		return null;
	}

	@Override
	public List<Request> getAllRequest(int start, int length, String sortBy, boolean desc) {
		Session session = HibernateUtil.getSession();
		requestDao.setSession(session);

		List<Request> result = requestDao.findAllWithSamples(start, length, sortBy, desc);

		session.close();

		return result;
	}

	@Override
	public Integer getRequestCount() {
		Session session = HibernateUtil.getSession();
		requestDao.setSession(session);

		Integer result = requestDao.getEntityCount();

		session.close();

		return result;
	}

	@Override
	public List<Request> getRequestByState(String state) {
		Session session = HibernateUtil.getSession();
		requestDao.setSession(session);

		List<Request> result = requestDao.findAllByState(state);

		session.close();

		return result;
	}

	@Override
	public List<Report> getReportsForRequest(Request request) {
		Session session = HibernateUtil.getSession();
		reportDao.setSession(session);

		List<Report> result = reportDao.findByRequest(request);

		session.close();
		return result;
	}

	@Override
	public void deleteReport(Long reportId) {
		Session session = HibernateUtil.getSession();
		reportDao.setSession(session);

		session.beginTransaction();

		reportDao.makeTransient(reportDao.findById(reportId, false));

		session.getTransaction().commit();

		session.close();
	}

}
